<?php
/*
邮件接收类
@author: yhbhiron
@time: 2011-8-23
@version:1.0.2
*/


class pop{
	
	/*邮件用户名*/
	private $mailUser =	MAIL_USER;
	
	/*邮件密码*/
	private $mailPwd = MAIL_PWD;
	
	/*邮件服务器地址*/
	private $server = MAIL_POP_HOST;
	
	/*邮件端口*/
	private $port = MAIL_POP_PORT;
	
	/*邮件超时时间*/
	public $timeout = MAIL_TIMEOUT;	
	public $useSSL = IN_SSL;
	public $showError = true;	
	public $charset = MAIL_CHARSET;
	public $attachDir = MAIL_ATTACH_DIR;
	
	private static $popCon;
	private $stop ="\r\n";
	private $status = 0;
	
	
	public function __construct(){
		
		if(self::$popCon){
			return;
		}
		
		if($this->mailUser==''){
			$this->error('请配置好邮件登录用户名!');
			return false;	
		}
		
		if($this->mailPwd==''){		
			$this->error('请配置好邮件登录密码!');
			return false;	
		}
		
		if(!strstr($this->server,'pop.')){			
			$this->error('请配置好邮服务器地址!');
			return false;	
		}
		
		if(!is_numeric($this->port)){			
			$this->error('请配置好邮服务器端口!');
			return false;	
		}
		$this->attachDir = addStrRight($this->attachDir,'/');
		/*ssl使用**/
		$server = $this->server;
		if($this->useSSL == true){
			$server = "ssl://".$this->server;	
		}
		
		self::$popCon = @fsockopen($server, $this->port, $errno, $errstr,10);;
		if(!self::$popCon){
			$this->error($errno.':无法连接到pop服务器');	
		}	
		
		socket_set_timeout(self::$popCon,0,250000);	
		$this->login();		
		
	}	
	
	/*
	获取未读邮件列表
	*/
	public function getUnreadMails(){
	
		if(!is_resource(self::$popCon)){
			return false;
		}
		
		$this->sendPopMsg('LIST');
		if(!$this->isRightState()){
			
			$this->error('获取邮件列表失败!');
			return false;
		}
		
		$line  = fgets(self::$popCon,1024);//移动一行
		$mails = $this->getPopMsg(true);
		
		if($mails==null){
			
			return null;	
		}

		$mLen  = count($mails);	
		$emails = array();
		for($i=1;$i<=$mLen;$i++){
			
			if($mails[$i-1]!=''){		
				$temp = preg_split('/\s+/',$mails[$i-1]);
				$emails[trim($temp[1])] = $this->getMailText($i);	
			}
		}
		unset($mails);
		return $emails;
	}
	
	
	/*
	删除邮件
	*/
	public function delecteMail($mid){
		
		$this->sendPopMsg('DELE '.$mid);	
	}
	
	/*
	关闭服务连接
	*/
	public function close(){
		$this->sendPopMsg('Quit');	
	}
	
	
	/*
	获取邮件服务器返回的信息
	@param boolean $list是否为显示列表命令
	@param $noEmpty 是否充许获取空行数据
	@return string 信息字符串
	*/
	protected function getPopMsg($list=false,$noEmpty=false){
				
		if(!is_resource(self::$popCon)){
			return false;
		}	
		
		
		if($list == false){
			
			$return = '';
			$line   = '';
			
			while (strpos($return, $this->stop)=== false)
			{
				$line    = fgets(self::$popCon,1024);
				$return .= $line;

			}
			return trim($return);	
			
		}else{
			
			$return = array();
			$line = '';
			
			while (trim($line)!='.' )
			{
				$line    = fgets(self::$popCon);	
				if(trim($line)!='.' && substr($line,0,3) != '+OK'){
					if($noEmpty == true && $line!=''){
						$return [] = trim($line);
					}else{
						$return [] = trim($line);
					}
				}
				
			}
			
			return $return;
		}
		
			
		
	}
	
	/*
	给邮件服务器发给指定命令消息
	*/
	protected function sendPopMsg($cmd,$chStatus=true){

        if (is_resource(self::$popCon))
        {
             return fwrite(self::$popCon, $cmd . $this->stop, strlen($cmd) + 2);
        }
		
		return false;
	}
	
	
	/*
	获取邮件的内容
	@param int $msgId邮件id;
	@return string 邮件内容
	*/
	protected function getMailText($msgId){
		
		if(!is_numeric($msgId)){
			return null;
		}

		$this->sendPopMsg('RETR '.$msgId);
		$this->isRightState();
		$this->isRightState();
		$txtArray = $this->getPopMsg(true);	
		
		file_put_contents('mail.log',var_export($txtArray,true));
		if($txtArray == null){
			return null;
		}

		$content = array();
		$content['boundary'] = $this->getBoundary($txtArray);	
		$maxLine = count($txtArray)-1;
		
		foreach($txtArray as $k=>$line){
			
			/*发件人*/
			if($content['from']==null && preg_match('/^From:\s*\"?(=\?(.+)\?([QB])\?)?(.+)/i',$line,$from)){
				
				if(strstr($from[4],'?=')){
					
					$ftemp = explode('?=',$from[4]);
					$from[4] = trim($ftemp[0]);
				}

				$content['from'] = $this->decodeMailTxt($from[4],$from[3],$from[2]).$ftemp[1];
				$content['from'] = preg_replace('/\'|\"|\s/','',$content['from']);
			}
			
			/*收件人*/
			if($content['to']==null && preg_match('/^to:\s*\"?(=\?(.+)\?([QB])\?)?(.+)/i',$line,$to)){
				
				if(strstr($to[4],'?=')){
					
					$ftemp = explode('?=',$to[4]);
					$to[4] = trim($ftemp[0]);
				}

				$content['to'] = $this->decodeMailTxt($to[4],$to[3],$to[2]).$ftemp[1];
				$content['to'] = preg_replace('/\'|\"|\s/','',$content['to']);
			}	
			
			/*主题*/
			if($content['subject']==null 
			&& preg_match('/^Subject:\s*(=\?(.+)\?([QB])\?)?(.+)(\?=)?/i',$line,$sub)){
				
				$sub[4] = str_replace('?=','',$sub[4]);								
				$content['subject'] = $this->decodeMailTxt($sub[4],$sub[3],$sub[2]);
				$cur = $k+1;
				$line = $txtArray[$cur];
				
				while(!$this->isItem($line)){
					if(preg_match('/(=\?(.+)\?([B|Q])\?)?(.+)(\?=)?/',$line,$s)){
						
						$s[4] = str_replace('?=','',$s[4]);
						$content['subject'].= $this->decodeMailTxt($s[4],$s[3],$s[2]);																   
					}
					
					$cur++;
					$line = $txtArray[$cur];
					next($txtArray);
				}
				
			}
			
			/*发送时间*/
			if($content['date'] == null && preg_match('/^Date:\s*(.+)/i',$line,$t)){
				
				$content['date'] = date('Y-m-d H:i:s',strtotime($t[1]));
			}
			
			/*编码*/
			if($content['charset']==null){
				
				$content['charset'] = $this->getCharset($line);
	
			}
				
			/*主要内容的读取*/
			if($content['boundary']!=null ){
				
				if( $this->isBoundary($line,$content['boundary'])){				
					
					$text       = '';
					$cur        = $k+1;
					$line       = $txtArray[$cur];
					$transfer   = '';
					$attachName = '';
					$lastRight  = '';
					
					while(!$this->isBoundary($line,$content['boundary']) && $cur<=$maxLine){	
						
						if(!$this->isItem($line) && $lastRight!=';'  ){
							if(trim($line)!=''){								
								/*一起解码*/
								if($attachName == ''){
									if($transfer == 'quoted-printable'){
										$text.= $content['charset']!=$this->charset ? iconv($content['charset'],$this->charset,quoted_printable_decode($line)) : quoted_printable_decode($line) ;							
									}else{
										$text.=$line;
									}
								}else{
									$text.=$line;	
								}
							}
							
						}else{
							
							if(preg_match('/^Content-Transfer-Encoding:\s*(.+)/i',$line,$t)){								
								$transfer = trim($t[1]);								
							}
							
							$lastRight = substr($line,-1,1);
						}
						
						/*编码*/
						if( $content['charset']==null){
							$content['charset'] = $this->getCharset($line);
						}	
						
						if($attachName == ''){
							$attachName = $this->getAttachName($line);	
						}
						
						$cur++;
						$line = $txtArray[$cur];						
						next($txtArray);
					}
					
					if($text!=''){ 
					
						if($content['text'] == null){						
							$content['text'] = array();						
						}						
						
						if($attachName == ''){
							
							if($transfer == 'base64'){									
								$text = $content['charset']!=$this->charset ? iconv($content['charset'],$this->charset,base64_decode($text)) : base64_decode($text) ;
							}else if($transfer == 'quoted-printable'){
								$text = $content['charset']!=$this->charset ? iconv($content['charset'],$this->charset,quoted_printable_decode($text)) : quoted_printable_decode($text) ;
							}
							
							$content['text'][] = $text; 
						}else{
							
							/*保存附件*/
							if($content['attach'] == null){
								$content['attach'] = array();
							}
							
							if($transfer == 'base64'){									
								$text =  base64_decode($text);
							}else if($transfer == 'quoted-printable'){
								$text = quoted_printable_decode($text);
							}
							
							$content['attach'][] = array('filename'=>$attachName,'path'=>$this->attachDir.$attachName);
							file_put_contents($this->attachDir.$attachName,$text);
						}
					}//eof text is not null
					unset($text);
				}
				
				
			}else{
				
				if(preg_match('/^Content-Transfer-Encoding:\s*(.+)/i',$line,$t)){								
					$transfer = trim($t[1]);
				}	
				
				if( $content['charset']==null){
					$content['charset'] = $this->getCharset($line);
				}
				
				if($line == ''){
					
					$cur = $k+1;
					$line = $txtArray[$cur];
					while($cur<=$maxLine){
											  
						if(trim($line)!='' && !$this->isItem($line)){								
						
							if($transfer == 'quoted-printable'){
								$text.= $content['charset']!=$this->charset ? iconv($content['charset'],$this->charset,quoted_printable_decode($line)) : quoted_printable_decode($line) ;							
							}else{
								$text.=$line;
							}
						}	
						
						$cur++;
						$line = $txtArray[$cur];						
						next($txtArray);
					}
					
					if($content['text'] == null){						
						$content['text'] = array();						
					}					
					if($text!=''){ 
						if($transfer == 'base64'){									
							$text = $content['charset']!=$this->charset ? iconv($content['charset'],$this->charset,base64_decode($text)) : base64_decode($text) ;
						}						
						$content['text'][] = $text; 
					}
					
					
				}//eof line
			}//eof text
			
		}//eof foreach
		
		unset($content['block']);
		unset($content['charset']);
		unset($content['boundary']);
		return $content;
	}
	
	/*
	登录
	*/
	private function login(){
		
		$this->sendPopMsg('USER '.$this->mailUser);
		if(!$this->isRightState()){
			$this->error('登录用户名错误');
			return false;
		}
		
		$this->sendPopMsg('PASS '.$this->mailPwd);
		if(!$this->isRightState()){
			$this->error('登录密码错误');
			return false;
		}

	}
	
	private function isRightState(){
		$msg = $this->getPopMsg();
		 if(substr($msg,0,3) == '+OK'){
			 return true;
		 }else{
			 return false;
		 }
		
	}
	
	/*
	是否为项目行
	*/
	private function isItem($line){
		
		return preg_match('/^[a-z-_]+:\s+.+/i',$line);	
	}
	
	/*
	获取邮件的分隔符
	*/
	private function getBoundary($text){
		
		if($text == null) return;
		$boundary = array();
		foreach($text as $k=>$line){			
			/*块分界线*/
			if(preg_match('/boundary=\"?(.+)/i',$line,$b)){	
				$boundary[] = preg_replace('/\"|\'/','',trim($b[1]));
			}				
		}
		return $boundary;
	}
	
	/*
	判断行是否为分隔符
	@param string $line 行内容
	@param array $boundary 分隔符数组
	*/
	private function isBoundary($line,$boundary){
		
		if($boundary == null){
			return false;
		}
		
		foreach($boundary as $k=>$b){
			
			if($line == '--'.$b || $line == '--'.$b.'--'){
				return true;
			}
		}
		
		return false;
	}
	
	/*
	获取附件文件名称
	*/
	private function getAttachName($line){
		
		if(preg_match('/^Content-disposition:\s*attachment;\s*(filename|name)=\"?(=\?(.+)\?([QB])\?)?(.+)(\?=)?/i',$line,$a)){
		$a[5] = preg_replace('/\"|\'|\s/','',$a[5]);
			return $this->decodeMailTxt($a[5],$a[4],$a[3]);																			  
	
		}
		
	}
	
	/*
	解码邮件文本
	@param string $txt邮件的文本内容
	@param string $decode 邮件文本的编码方式
	@param string $charset 邮件文本的字符集
	*/
	private function decodeMailTxt($txt,$decode,$charset){
		
		if($decode == ''){

		}else if(strtolower($decode) == 'b'){
			$txt = base64_decode($txt);
		}else if(strtolower($decode) == 'q'){
			$txt = quoted_printable_decode($txt);
		}
		
		if($charset!='' && $charset!= $this->charset){
			
			$txt = iconv($charset,$this->charset,$txt);
		}
						
		return $txt;
	}
	
	private function getCharset($line){
		
		/*编码*/
		if(preg_match('/charset=\"?(.+)\"?(;.+)?/i',$line,$char)){
			
			$charset = strtolower($char[1]);				
			if(strstr($charset,';')){
				$tmp = explode(';',$charset);
				$charset = $tmp[0];
			}
			
			$charset = preg_replace('/\'|\"/','',$charset);
			
			return $charset;
		}	
	}
	/*
	异常报告
	*/
	private function error($exception){	
		
		if($this->showError == false){
			return;
		}
		
		throw new Exception($exception);		
	}
	
	function __destruct(){
		
		fclose(self::$popCon);	
	}
	
	
}


/*示例子*/

ignore_user_abort(false);
set_time_limit(360);
define('IN_WEB','');

ob_implicit_flush();
define('MAIL_POP_HOST','pop.163.com');
define('MAIL_USER','yhbhiron');
define('MAIL_PWD','yhb1279562250');
define('MAIL_POP_PORT',110);
define('IN_SSL',false);
define('MAIL_TIMEOUT',30);
define('MAIL_CHARSET','utf-8');
define('MAIL_ATTACH_DIR','attachment/');

require('../global.php');
//$f = @fopen('a.jpg', 'r');
//$attachment = @fread($f, filesize('a.jpg'));
//$attachment = base64_encode($attachment);
//$attachment = chunk_split($attachment);
//echo file_put_contents('get_img.jpg',base64_decode($attachment));
//exit;
//echo now().'<br />';
$p = new pop();

print_r($p->getUnreadMails());
$p->close();

?>